use lettre::{message::{Mailbox, IntoBody, header}, transport::smtp::{authentication::Credentials, response::Response, Error}, Address, Message, Transport};

use super::{EmailBody, EmailBuild, EmailSend};




pub struct QQEmail< T: IntoBody>{
	from_name: Option<String>,
    to: Vec<Mailbox>,
    cc: Vec<Mailbox>,
    bcc: Vec<Mailbox>,
    subject: Option<String>,
    body: EmailBody<T>,
}
impl< T: IntoBody> Default for QQEmail<T> {
    fn default() -> Self {
        QQEmail {
            from_name: None,
            to: vec![],
            cc: vec![],
            bcc: vec![],
            subject: None,
            body: EmailBody::Null,
        }
    }
}

impl< T: IntoBody> EmailBuild<T> for QQEmail<T> {
    fn get_credentials() -> Credentials {
		let config = &crate::tool_bag::FREE_CONFIG.qq_email;
		Credentials::new(config.account.clone(), config.code.clone())
    }

    fn get_smtp_servers() -> &'static str {
        "smtp.qq.com"
    }

    fn get_mailbox(s: Option<impl Into<String>>) -> Mailbox  {
		let config = &crate::tool_bag::FREE_CONFIG.qq_email;
		let address = Address::new(config.account.clone(),Self::get_at_behind())
			.expect("电子邮件地址解析错误"); //电子邮件地址解析错误...,应该不会错
		if let None = s {
			if let Some(_) = &config.name {
				return Mailbox::new(config.name.clone(),address);
			}
			return Mailbox::new(None, address);
		}
		Mailbox::new(Some(s.unwrap().into()), address)
	}

    fn get_at_behind()-> &'static str {
        "qq.com"
    }

    fn build() -> Self {
		Self::default()
    }

    fn from_name(mut self,s:impl Into<String>) -> Self {
        self.from_name = Some(s.into());
		self
    }

    fn to(mut self,to:Vec<impl Into<Address>>) -> Self {
		for v in to {
			self.to.push(
				Mailbox::new(None
				,v.into()))
		}
        self
    }

    fn cc(mut self,cc:Vec<impl Into<Address>>) -> Self {
        for v in cc {
			self.cc.push(
				Mailbox::new(None
				,v.into()))
		}
        self
    }

    fn bcc(mut self,bcc:Vec<impl Into<Address>>) -> Self {
		for v in bcc {
			self.bcc.push(
				Mailbox::new(None
				,v.into()))
		}
        self
    }

    fn subject(mut self,subject:impl Into<String>)->Self {
        self.subject = Some(subject.into());
		self
    }

    fn body(mut self,body:EmailBody<T>) -> Self {
        self.body = body;
		self
    }
}

impl<T: IntoBody> EmailSend for QQEmail<T> {

    fn send(self)->Result<Response, Error> {
        let mut email = Message::builder()
			.from(Self::get_mailbox(self.from_name));
		email = match self.subject {
            Some(v) => email.subject(v),
            None => email.subject(""),
        };
		for v in self.to {
            email = email.to(v);
        }
        for v in self.cc {
            email = email.cc(v);
        }
        for v in self.bcc {
            email = email.bcc(v);
        }
		let email = match self.body {
            EmailBody::Text(v) => {
                email = email.header(header::ContentType::TEXT_PLAIN);
                email.body(v)
            }
            EmailBody::Html(v) => {
                email = email.header(header::ContentType::TEXT_HTML);
                email.body(v)
            }
            EmailBody::Null => email.body(String::new()),
        };
		let email = email.expect("[Err]:邮件格式不应该失败");
		Self::get_smtp_transport().send(&email)
    }
}